﻿#include "FITKAbaInteractionGeneralContactExplicit.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKBoundaryLocation.h"
#include <QMapIterator>


bool Interface::FITKAbaInteractionGeneralContactExplicit::copy(FITKAbstractDataObject *obj)
{
    bool ok = FITKAbaAbstractInteraction::copy(obj);
    if (!ok)
        return false;
    FITKAbaInteractionGeneralContactExplicit* exp = dynamic_cast<FITKAbaInteractionGeneralContactExplicit*>(obj);
    if (exp == nullptr)
        return false;
    this->m_data.copy(&exp->m_data);
    this->m_modifiedDatas.clear();
    for (int i : exp->m_modifiedDatas.keys())
    {
        this->m_modifiedDatas[i] = new GeneralContactExplicitData;
        this->m_modifiedDatas[i]->copy(exp->m_modifiedDatas[i]);
    }
    return true;
}

bool Interface::FITKAbaInteractionGeneralContactExplicit::isModifiedInStep(int stepId) const
{
    //根据后续分析步修改的数据判断是否更改
    if (stepId <= 0 || stepId == m_createdStepId)
        return false;
    if (m_modifiedDatas.contains(stepId))
        return true;
    return false;
}

void Interface::FITKAbaInteractionGeneralContactExplicit::activeStateChanged()
{
    if (m_deactiveStepId == -1)
        return;
    //访问当前算例的分析步管理器，获取分析步顺序id列表。
    QVector<int> stepIds = this->getStepIds();
    int index = stepIds.indexOf(m_deactiveStepId);
    if (index == -1)
        return;
    for (int i = index; i < stepIds.count(); ++i)
    {
        int id = stepIds[i];
        //清理后续分析步修改的数据
        if (m_modifiedDatas.contains(id))
        {
            delete m_modifiedDatas[id];
            m_modifiedDatas.remove(id);
        }
    }
}

Interface::FITKAbaAbstractInteraction::FITKAbaInteractionType Interface::FITKAbaInteractionGeneralContactExplicit::getInteractionType() const
{
    return FITKAbaInteractionType::GeneralContactExplicit;
}

Interface::GeneralContactExplicitData::IncludeSurfacePairs Interface::FITKAbaInteractionGeneralContactExplicit::getIncludeSurfacePairs(int stepId )
{
    return this->getStepData(stepId).getIncludeSurfacePairs();
}

void Interface::FITKAbaInteractionGeneralContactExplicit::setIncludeSurfacePairs(GeneralContactExplicitData::IncludeSurfacePairs type, int stepId)
{
    if (stepId <= 0 || stepId == m_createdStepId)
        m_data.setIncludeSurfacePairs(type);
    else
    {
        if (!m_modifiedDatas.contains(stepId))
        {
            m_modifiedDatas[stepId] = new GeneralContactExplicitData;
            m_modifiedDatas[stepId]->copy(&this->getStepData(stepId));
        }
        m_modifiedDatas[stepId]->setIncludeSurfacePairs(type);
    }
}

void Interface::FITKAbaInteractionGeneralContactExplicit::setNumberOfIncludeSurfPairs(int num, int stepId /*= 0*/)
{
    if (stepId <= 0 || stepId == m_createdStepId)
        m_data.setNumberOfIncludeSurfPairs(num);
    else
    {
        if (!m_modifiedDatas.contains(stepId))
        {
            m_modifiedDatas[stepId] = new GeneralContactExplicitData;
            m_modifiedDatas[stepId]->copy(&this->getStepData(stepId));
        }
        m_modifiedDatas[stepId]->setNumberOfIncludeSurfPairs(num);
    }
}

int Interface::FITKAbaInteractionGeneralContactExplicit::getNumberOfIncludeSurfPairs(int stepId /*= 0*/)
{
    return this->getStepData(stepId).getNumberOfIncludeSurfPairs();
}

QPair<Interface::FITKBoundaryLocation*, Interface::FITKBoundaryLocation*> Interface::FITKAbaInteractionGeneralContactExplicit::getIncludeSurfPair(int index, int stepId /*= 0*/)
{
    return this->getStepData(stepId).getIncludeSurfPair(index);
}

void Interface::FITKAbaInteractionGeneralContactExplicit::removeIncludeSurfPair(int index, int stepId /*= 0*/)
{
    if (stepId <= 0 || stepId == m_createdStepId)
        m_data.removeIncludeSurfPair(index);
    else
    {
        if (!m_modifiedDatas.contains(stepId))
        {
            m_modifiedDatas[stepId] = new GeneralContactExplicitData;
            m_modifiedDatas[stepId]->copy(&this->getStepData(stepId));
        }
        m_modifiedDatas[stepId]->removeIncludeSurfPair(index);
    }
}

void Interface::FITKAbaInteractionGeneralContactExplicit::celarIncludeSurfPairs(int stepId /*= 0*/)
{
    this->getStepData(stepId).celarIncludeSurfPairs();
}

int Interface::FITKAbaInteractionGeneralContactExplicit::getContactPropertyId(int stepId )
{
    return this->getStepData(stepId).getContactPropertyId();
}

void Interface::FITKAbaInteractionGeneralContactExplicit::setContactPropertyId(int id, int stepId )
{
    if (stepId <= 0 || stepId == m_createdStepId)
        m_data.setContactPropertyId(id);
    else
    {
        if (!m_modifiedDatas.contains(stepId))
        {
            m_modifiedDatas[stepId] = new GeneralContactExplicitData;
            m_modifiedDatas[stepId]->copy(&this->getStepData(stepId));
        }
        m_modifiedDatas[stepId]->setContactPropertyId(id);
    }
}

Interface::GeneralContactExplicitData& Interface::FITKAbaInteractionGeneralContactExplicit::getStepData(int stepId)
{
    if (stepId <= 0 || stepId == m_createdStepId)
        return  m_data;
    if (m_modifiedDatas.contains(stepId))
        return *m_modifiedDatas[stepId];
    QVector<int> stepIds = this->getStepIds();
    int createdStepIndex = stepIds.indexOf(m_createdStepId);
    int stepIndex = stepIds.indexOf(stepId);
    if (!(createdStepIndex >= 0 && createdStepIndex < stepIds.size()))
        return m_data;
    if (!(stepIndex >= 0 && stepIndex < stepIds.size()))
        return m_data;
    for (int i = stepIndex; i >= createdStepIndex; --i)
    {
        int id = stepIds.at(i);
        if (m_modifiedDatas.contains(id))
            return *m_modifiedDatas[id];
    }
    return m_data;
}

bool Interface::GeneralContactExplicitData::copy(Core::FITKAbstractDataObject* obj)
{
    bool ok = FITKInteractionLocation::copy(obj);
    if (!ok)
        return false;
    Interface::GeneralContactExplicitData* data = dynamic_cast<Interface::GeneralContactExplicitData*>(obj);
    if (data == nullptr)
        return false;
    this->m_includeSurfPairs = data->m_includeSurfPairs;
    this->m_contactPropertyID = data->m_contactPropertyID;
    return true;
}

Interface::GeneralContactExplicitData::IncludeSurfacePairs Interface::GeneralContactExplicitData::getIncludeSurfacePairs() const
{
    return m_includeSurfPairs;
}

void Interface::GeneralContactExplicitData::setIncludeSurfacePairs(IncludeSurfacePairs type)
{
    m_includeSurfPairs = type;
}

void Interface::GeneralContactExplicitData::setNumberOfIncludeSurfPairs(int num)
{
    int currentNum = this->getNumberOfIncludeSurfPairs();
    if (currentNum < num)
        this->getLocationAt(num * 2 - 1);
    else if (currentNum > num)
    {
        QList<int> indexToRemove{};
        for (int i = num * 2; i < this->getLocationCount(); ++i)
        {
            indexToRemove.append(i);
        }
        this->removeLocationAt(indexToRemove);
    }
    else;
}

void Interface::GeneralContactExplicitData::addIncludeSurfPair()
{
    int currentNum = this->getNumberOfIncludeSurfPairs();
    this->getLocationAt((currentNum + 1) * 2 - 1);
}

int Interface::GeneralContactExplicitData::getNumberOfIncludeSurfPairs() const
{
    int num = this->getLocationCount() / 2;
    return num;
}

QPair<Interface::FITKBoundaryLocation*, Interface::FITKBoundaryLocation*> Interface::GeneralContactExplicitData::getIncludeSurfPair(int index)
{
    FITKBoundaryLocation* first = this->getLocationAt(index * 2 + 0);
    FITKBoundaryLocation* second = this->getLocationAt(index * 2 + 1);
    return { first, second };
}

void Interface::GeneralContactExplicitData::removeIncludeSurfPair(int index)
{
    this->removeLocationAt(index * 2, index * 2 + 1);
}

void Interface::GeneralContactExplicitData::celarIncludeSurfPairs()
{
    int num = this->getNumberOfIncludeSurfPairs();
    for (int i = 0; i < num; ++i)
        this->removeIncludeSurfPair(i);
}

int Interface::GeneralContactExplicitData::getContactPropertyId() const
{
    return m_contactPropertyID;
}

void Interface::GeneralContactExplicitData::setContactPropertyId(int id)
{
    m_contactPropertyID = id;
}
